/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package mygame.Backbone;

import mygame.Manager;

import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.input.FlyByCamera;
import com.jme3.input.InputManager;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseAxisTrigger;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;

/**
 *
 * @author Tobi
 */
public class MyCamera extends FlyByCamera implements ICam{

    Vector3f walkDirection;
    private CharacterControl player;
    private boolean left = false, right = false, up = false, down = false;

    public MyCamera(Camera cam, InputManager input) {
        super(cam);
        this.inputManager = input;
        setMoveSpeed(15f);

        walkDirection = new Vector3f(0, 0, 0);
    }

    public void update(float tpf) {
        Vector3f camDir = cam.getDirection().clone().multLocal(0.6f);
        Vector3f camLeft = cam.getLeft().clone().multLocal(0.4f);
        walkDirection.set(0, 0, 0);
        if (left) {
            walkDirection.addLocal(camLeft);
            //left = false;
        }
        if (right) {
            walkDirection.addLocal(camLeft.negate());
            //right = false;
        }
        if (up) {
            walkDirection.addLocal(camDir);
            //up = false;
        }
        if (down) {
            walkDirection.addLocal(camDir.negate());
            //down = false;
        }
        player.setWalkDirection(walkDirection.multLocal(0.3f));
        cam.setLocation(player.getPhysicsLocation());
    }

    public void registerWithInput() {
        this.inputManager = inputManager;

        String[] mappings = new String[]{
            "FLYCAM_Left",
            "FLYCAM_Right",
            "FLYCAM_Up",
            "FLYCAM_Down",
            "FLYCAM_StrafeLeft",
            "FLYCAM_StrafeRight",
            "FLYCAM_Forward",
            "FLYCAM_Backward",
            "FLYCAM_Rise",
            "FLYCAM_Lower"
        };

        // both mouse and button - rotation of cam
        inputManager.addMapping("FLYCAM_Left", new MouseAxisTrigger(MouseInput.AXIS_X, true),
                new KeyTrigger(KeyInput.KEY_LEFT));

        inputManager.addMapping("FLYCAM_Right", new MouseAxisTrigger(MouseInput.AXIS_X, false),
                new KeyTrigger(KeyInput.KEY_RIGHT));

        inputManager.addMapping("FLYCAM_Up", new MouseAxisTrigger(MouseInput.AXIS_Y, false),
                new KeyTrigger(KeyInput.KEY_UP));

        inputManager.addMapping("FLYCAM_Down", new MouseAxisTrigger(MouseInput.AXIS_Y, true),
                new KeyTrigger(KeyInput.KEY_DOWN));

        // keyboard only WASD for movement and WZ for rise/lower height
        inputManager.addMapping("FLYCAM_StrafeLeft", new KeyTrigger(KeyInput.KEY_A));
        inputManager.addMapping("FLYCAM_StrafeRight", new KeyTrigger(KeyInput.KEY_D));
        inputManager.addMapping("FLYCAM_Forward", new KeyTrigger(KeyInput.KEY_W));
        inputManager.addMapping("FLYCAM_Backward", new KeyTrigger(KeyInput.KEY_S));
        inputManager.addMapping("FLYCAM_Rise", new KeyTrigger(KeyInput.KEY_SPACE));
        inputManager.addMapping("FLYCAM_Lower", new KeyTrigger(KeyInput.KEY_LCONTROL));

        inputManager.addListener(this, mappings);
        inputManager.setCursorVisible(dragToRotate);
    }

    @Override
    public void onAction(String name, boolean value, float tpf) {
        super.onAction(name, value, tpf);
        if (name.equals("FLYCAM_Forward")) {
            if (value) {
                this.up = true;
            } else {
                this.up = false;
            }
        } else if (name.equals("FLYCAM_Backward")) {
            if (value) {
                this.down = true;
            } else {
                this.down = false;
            }
        } else if (name.equals("FLYCAM_StrafeLeft")) {
            if (value) {
                this.left = true;
            } else {
                this.left = false;
            }
        } else if (name.equals("FLYCAM_StrafeRight")) {
            if (value) {
                this.right = true;
            } else {
                this.right = false;
            }
        } else if (name.equals("FLYCAM_Rise")) {
            player.jump();
        }
    }

    @Override
    public void onAnalog(String name, float value, float tpf) {
        if (!enabled) {
            return;
        }
        if (name.equals("FLYCAM_Left")) {
            rotateCamera(value, initialUpVec);
        } else if (name.equals("FLYCAM_Right")) {
            rotateCamera(-value, initialUpVec);
        } else if (name.equals("FLYCAM_Up")) {
            rotateCamera(-value, cam.getLeft());
        } else if (name.equals("FLYCAM_Down")) {
            rotateCamera(value, cam.getLeft());
        } else if (name.equals("FLYCAM_Lower")) {
            riseCamera(-value);
        }


    }

  
    public void init() {
        CapsuleCollisionShape shape = new CapsuleCollisionShape(1.5f, 6f, 1);
        player = new CharacterControl(shape, 1f);
        player.setJumpSpeed(20);
        player.setGravity(30);
        player.setFallSpeed(30);
        player.setPhysicsLocation(new Vector3f(0, 20, 0));
        Manager.GetInstance().getPhysix().getPhysicsSpace().add(player);
    }

    public void setPlayerPosition(Vector3f v){
        this.player.setPhysicsLocation(v);
    }
    
    public Camera getCamera() {
        return this.cam;
    }

    public String savePlayerPosition() {
        String save = "";
        save += player.getPhysicsLocation().x + "," + player.getPhysicsLocation().y + "," + player.getPhysicsLocation().z;
        save += GlobalVars.DELIMITER_OBJECTS;
        save += cam.getDirection().x + "," + cam.getDirection().y + "," + cam.getDirection().z;
        
        return save;
    }

    public void loadPlayerPosition(String s) {
        String[] o = s.split(GlobalVars.DELIMITER_OBJECTS);
        String[] t = o[0].split(",");
        player.setPhysicsLocation(new Vector3f(Float.parseFloat(t[0]), Float.parseFloat(t[1]) + 1f, Float.parseFloat(t[2])));
        cam.setLocation(player.getPhysicsLocation());
        t = o[1].split(",");
        cam.lookAtDirection(new Vector3f(Float.parseFloat(t[0]), Float.parseFloat(t[1]), Float.parseFloat(t[2])), Vector3f.UNIT_Y);
    }
}
